package com.github.pig.auth.component.mobile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pig.auth.feign.AppUserService;
import com.github.pig.common.constant.CommonConstant;
import com.github.pig.common.constant.ExceptionConstant;
import com.github.pig.common.constant.SecurityConstants;
import com.github.pig.common.util.AuthUtils;
import com.github.pig.common.util.R;
import com.xiaoleilu.hutool.map.MapUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author lengleng
 * @date 2018/1/8
 * 手机号登录成功，返回oauth token
 */
@Component
public class MobileLoginSuccessHandler implements AuthenticationSuccessHandler {
    public static final String BASIC_ = "Basic ";
    public static final String APP_COMMUNITY = "app_community";
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;
    private AppUserService userService;
    @Autowired
    public RedisTemplate redisTemplate;

    /**
     * Called when a user has been successfully authenticated.
     * 调用spring security oauth API 生成 oAuth2AccessToken
     *
     * @param request        the request which caused the successful authentication
     * @param response       the response
     * @param authentication the <tt>Authentication</tt> object which was created during
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        String header = request.getHeader("Authorization");
        response.setCharacterEncoding(CommonConstant.UTF8);
        response.setContentType(CommonConstant.CONTENT_TYPE);
        R<String> result = new R<>();
        if (header == null || !header.startsWith(BASIC_)) {
            throw new UnapprovedClientAuthenticationException("请求头中client信息为空");
        }

        try {
            PrintWriter printWriter = response.getWriter();
            String[] tokens = AuthUtils.extractAndDecodeHeader(header);
            assert tokens.length == 2;
            String clientId = tokens[0];

            ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
            TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(), "mobile");
            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

            //此处开始进行验证码登录逻辑判断
            if (StringUtils.isNotBlank(clientId) && clientId.equals(APP_COMMUNITY)) { //智慧社区app
                //MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;
                String mobile = request.getParameter("mobile");
                String grandType = request.getParameter("grant_type");
                String code = request.getParameter("code");
                if("mobile".equals(grandType)){//手机登陆
                    if (StringUtils.isBlank(mobile)) {

                        result.setData(ExceptionConstant.phoneCodeException);
                        response.setStatus(ExceptionConstant.phoneCode);
                        printWriter.append(objectMapper.writeValueAsString(result));
                        return;
//                        throw new UsernameNotFoundException("手机号为空");
                    }
                    Object data = redisTemplate.opsForValue().get(SecurityConstants.DEFAULT_CODE_KEY + mobile);
                    if (data != null) {
                        String codeStor = data.toString();
                        if (StringUtils.isBlank(codeStor)) {
                            result.setData(ExceptionConstant.yzmCodeException);
                            response.setStatus(ExceptionConstant.yzmCode);
                            printWriter.append(objectMapper.writeValueAsString(result));
                            return;
//                            throw new UsernameNotFoundException("验证码已过期");
                        }else if(!codeStor.equals(code)){
                            result.setData(ExceptionConstant.yzmCodeException);
                            response.setStatus(ExceptionConstant.yzmCode);
                            printWriter.append(objectMapper.writeValueAsString(result));
                            return;
//                            throw new UsernameNotFoundException("验证码不正确");
                        }
                    } else {
                        result.setData(ExceptionConstant.yzmCodeException);
                        response.setStatus(ExceptionConstant.yzmCode);
                        printWriter.append(objectMapper.writeValueAsString(result));
                        return;
//                        throw new UsernameNotFoundException("验证码已过期");
                    }
                }

            }
            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
            OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
            logger.info("获取token 成功：{}", oAuth2AccessToken.getValue());
            printWriter.append(objectMapper.writeValueAsString(oAuth2AccessToken));
        } catch (IOException e) {
            throw new BadCredentialsException(
                    "Failed to decode basic authentication token");
        }
    }


}
